package com.meme.io.editor;

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;

import javax.imageio.ImageIO;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;

import com.meme.editor.EntityObject;
import com.meme.editor.model.sprite2d.Sprite2dFile;
import com.meme.editor.level.LevelFile;
import com.meme.editor.level.define.DefineFile;
import com.meme.util.FileUtil;
import com.meme.util.ObjectCollector;
import com.meme.util.XmlUtil;


public class FileCache 
{
	static Logger logger = Logger.getLogger (FileCache.class);	

	static Hashtable <File, Object> sLoadedFiles = new Hashtable <File, Object> ();
	
	//static Hashtable <File, BufferedImage> sLoadedImages = new Hashtable <File, BufferedImage> ();
	
	static ObjectCollector<File> mFileCollector = new ObjectCollector<File> ();
	
	public static ObjectCollector<File> getFileCollector ()
	{
		return mFileCollector;
	}
	
	public static Object getLoadedFileAsset (File file)
	{
		return sLoadedFiles.get (file);
	}
	
	public static Object getLoadedFileAsset (String filepath)
	{
		File file = FileUtil.getFile (filepath);
		return sLoadedFiles.get (file);
	}
	
	public static void registerLoadedFileAsset (String filepath, Object asset)
	{
		File file = FileUtil.getFile (filepath);
		registerLoadedFileAsset (file, asset);
	}
	
	public static void registerLoadedFileAsset (File file, Object asset)
	{
		sLoadedFiles.put (file, asset);
		mFileCollector.addObject (file);
	}
	
	public static BufferedImage getImage (String filepath)
	{
		if (filepath.trim().length () == 0)
			return null;
		File file = FileUtil.getFile (filepath);
		if (!file.exists())
			return null;
		
		Object object = getLoadedFileAsset (file);
		
		BufferedImage image = null;
		if (object instanceof BufferedImage)
			image = (BufferedImage) object;

		
		if (image == null)
		{
			try
			{
				image = ImageIO.read (file);
				
				registerLoadedFileAsset (file, image);
			}
			catch (Exception e)
			{
				logger.error("Creating BufferedImage with filename [" + filepath + "] failed" );
			}
		}
		
		return image;		
	}
	
	
	//static Hashtable <File, Sprite2dFile> sLoadedSprite2dFiles = new Hashtable <File, Sprite2dFile> ();
	
	public static Sprite2dFile getSprite2dFile (String filepath)
	{
		if (filepath.trim().length () == 0)
			return null;
		File file = FileUtil.getFile (filepath);
		if (!file.exists())
			return null;
		
		Object object = sLoadedFiles.get (file);
		
		Sprite2dFile sprite2dFile = null;
		if (object instanceof Sprite2dFile)
			sprite2dFile = (Sprite2dFile) object;
		
		if (sprite2dFile == null)
		{
			try
			{
				boolean done = true;
				Document document = XmlUtil.loadXmlFile (filepath);
				
				if (XmlUtil.getChildElementByName (document, "Sprite2d") != null)
				{
					sprite2dFile = new Sprite2dXmlFileLoader ().loadFromXmlDocument(document, filepath);
				}
				else if (XmlUtil.getChildElementByName (document, "Animation") != null)
				{
					sprite2dFile = new AnimXmlFileLoader ().loadFromXmlDocument(document, filepath);
				}
				else if (XmlUtil.getChildElementByName (document, "Map") != null)
				{
					sprite2dFile = new PlayfieldXmlFileLoader ().loadFromXmlDocument(document, filepath);
				}
				else
					done = false;
				
				if (done)
				{
					registerLoadedFileAsset (file, sprite2dFile);
				}
			}
			catch (Exception e)
			{
				e.printStackTrace();
				logger.error("Create sprite2d file error: " + filepath);
			}
		}
		
		return sprite2dFile;
	}
	
	
	//static Hashtable <File, LevelFile> sLoadedLevelFiles = new Hashtable <File, LevelFile> ();
	
	public static LevelFile getLevelFile (String filepath)
	{
		if (filepath.trim().length () == 0)
			return null;
		File file = FileUtil.getFile (filepath);
		if (!file.exists())
			return null;
		
		Object object = sLoadedFiles.get (file);
		
		LevelFile levelFile = null;
		if (object instanceof LevelFile)
			levelFile = (LevelFile) object;		

		
		if (levelFile == null)
		{
			try
			{
				Document document = XmlUtil.loadXmlFile (filepath);
				
				levelFile = new LevelXmlFileLoader ().loadFromXmlDocument(document, filepath);
				
				registerLoadedFileAsset (file, levelFile);
			}
			catch (Exception e)
			{
				e.printStackTrace();
				logger.error("Create level file error: " + filepath);
			}
		}
		
		return levelFile;
	}
	
	public static DefineFile getDefineFile (String filepath)
	{
		if (filepath.trim().length () == 0)
			return null;
		File file = FileUtil.getFile (filepath);
		if (!file.exists())
			return null;
		
		Object object = sLoadedFiles.get (file);
		
		DefineFile defineFile = null;
		if (object instanceof DefineFile)
			defineFile = (DefineFile) object;
		
		if (defineFile == null)
		{
			try
			{
				Document document = XmlUtil.loadXmlFile (filepath);
				
				defineFile = new DefineXmlFileLoader ().loadFromXmlDocument(document, filepath);
				
				registerLoadedFileAsset (file, defineFile);
			}
			catch (Exception e)
			{
				e.printStackTrace();
				logger.error("Create define file error: " + filepath);
			}
		}
		
		return defineFile;
	}
}
